import Vue from 'vue'
import i18n from '@/assets/lang'
import { Message } from 'element-ui';
// import  不带 {}  一定对应于 export default
// require  对应于  module.exports or  export default
import { removeToken } from "@/utils/auth.js"
import router from "@/router"

function isObj(o){
  return (Object.prototype.toString.call(o) == '[object Object]'||Object.prototype.toString.call(o) == '[object Array]') && o != null;
}
function isLoop(arr, item){
  for(var i = 0, len=arr.length; i < len; i++){
    if(arr[i].source == item){
      return arr[i];
    }
  }
  return false;
}
export function deepClone(source, container=[]){
  if(!isObj(source)){ return source }
  let res = Array.isArray(source)? [] : {};
  let checkRes = isLoop(container, source);
  if(checkRes){return checkRes.res}
  container.push({source: source, res: res});
  for(let key in source){
    if(Object.prototype.hasOwnProperty.call(source, key)){
      if(isObj(source[key])){
        res[key] = deepClone(source[key], container);
      }else {
        res[key] = source[key];
      }
    }
  }
  return res;
}

export function buildTree(arr, id, pid) {
  let temp = {}
  let tree = {}
  // 数组转 键值对
  arr.forEach(item => {
      temp[item[id]] = item
  })

  let tempKeys = Object.keys(temp)
  tempKeys.forEach(key => {
      // 获取当前项
      let item = temp[key]
      // 当前项 pId
      let _itemPId = item[pid]
      // 获取父级项
      let parentItemByPid = temp[_itemPId]
      if (parentItemByPid) {
          if (!parentItemByPid.children) {
              parentItemByPid.children = []
          }
          parentItemByPid.children.push(item)
      } else {
          tree[item[id]] = item
      }
  })
  // 对象转数组并返回
  return Object.keys(tree).map(key => tree[key])
}
// json对象类型转数组, 对象数组
export function obj_to_arr(source, map, arr=[]){
  map.forEach((item, idx) => {
    Vue.prototype.$set(arr, idx, source[item])
  })
  return arr
}
// 数组类型数据 转 json对象数据
export function arr_to_obj(arr, map){
  let obj = {};
  map.forEach((item, idx) => {
    item!='' ? obj[item] = arr[idx] : ''
  })
  return obj
}
// 时间格式化
export function formatDuration(seconds){
  if (seconds < 0) seconds = -seconds;
  if (seconds == "0") return "--";
  const time = {
    day: Math.floor(seconds / 86400),  // 最高位取模
    hour: Math.floor(seconds / 3600) % 24,  // 其余位取余
    minute: Math.floor(seconds / 60) % 60,
    second: Math.floor(seconds) % 60,
  };
  switch(i18n.locale){
    case "en" :
      return `${time.day?time.day+"d ":""}${time.hour?time.hour+"h ":''}
      ${time.minute?time.minute+"m ":''}${time.second?time.second+"s ":''}`
    case "zh" :
      return `${time.day?time.day+"天 ":""}${time.hour?time.hour+"小时 ":''}
      ${time.minute?time.minute+"分钟 ":''}${time.second?time.second+"秒 ":''}`
  }
  // return Object.entries(time)
  //   .filter(val => val[1] !== 0)
  //   .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
  //   .join(', ');
}

function transfer_total_traffic(origin){
  // if(origin){
  //   let origin = Number(origin)
  //   if(origin < 1024){
  //     let count = origin / 1024
  //     let result = Math.floor(count*100)
  //     return result / 100 + 'KB'
  //   } else if(origin < 1024*1024) {
  //     let count = origin / 1024*1024
  //     let result = Math.floor(count*100)
  //     return result / 100 + 'MB'
  //   }
  //   let count = Number(origin) / (1024*1024*1024)
  //   let result = Math.floor(count*100)
  //   return result / 100 + 'GB'
  // } else {
  //   return '--'
  // }
  if(origin){
//     if (bytes === 0) return '0 B';
// 　　var k = 1024;
// 　　sizes = ['B','KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
// 　　i = Math.floor(Math.log(bytes) / Math.log(k))　　
// 　　//return (bytes / Math.pow(k, i))   ' '   sizes[i];
// 　　return (bytes / Math.pow(k, i)).toPrecision(3)   ' '   sizes[i];
    let bytes = Number(origin);
    bytes < 0 ? bytes = -bytes : ""
    if (bytes === 0) return '--';
    // if (bytes === 0) return '0 B';
　  let k = 1024, 
　  sizes = ['B','KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
　　i = Math.floor(Math.log(bytes) / Math.log(k));　
　　return (bytes / Math.pow(k, i)).toPrecision(3) + sizes[i];
// 　　return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
  } else {
    return "--"
  }
}

let formatByte = transfer_total_traffic

function value_to_label(arr, value){
  let label;
  arr.forEach(item=> {
    if(item.value == value){
      label = item.label
    }
  })
  return label
}

/**
 * 日期格式化函数
 * @param date Date 类型
 * @param fmt 需要格式化的样式
 * @returns {void | string}
 */
function dateFormat(date, fmt){
    var o = {
        "Y+" : date.getFullYear(),
        "M+" : date.getMonth()+1,                 //月份
        "D+" : date.getDate(),                    //日
        "h+" : date.getHours(),                   //小时
        "m+" : date.getMinutes(),                 //分
        "s+" : date.getSeconds(),                 //秒
        "q+" : Math.floor((date.getMonth()+3)/3), //季度
        "S"  : date.getMilliseconds()             //毫秒
    };
    if(/(y+)/.test(fmt))
        fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
    for(var k in o)
        if(new RegExp("("+ k +")").test(fmt))
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
    return fmt;
}

Date.prototype.Format = function (formatStr) {
     var Week = ['日', '一', '二', '三', '四', '五', '六'];
     var str = formatStr;

     str = str.replace(/yyyy|YYYY/, this.getFullYear());
     str = str.replace(/yy|YY/, (this.getYear() % 100) > 9 ? (this.getYear() % 100).toString() : '0' + (this.getYear() % 100));
     var month = this.getMonth() + 1;
     str = str.replace(/MM/, month > 9 ? month.toString() : '0' + month);
     str = str.replace(/M/g, month);

     str = str.replace(/w|W/g, Week[this.getDay()]);

     str = str.replace(/dd|DD/, this.getDate() > 9 ? this.getDate().toString() : '0' + this.getDate());
     str = str.replace(/d|D/g, this.getDate());

     str = str.replace(/hh|HH/, this.getHours() > 9 ? this.getHours().toString() : '0' + this.getHours());
     str = str.replace(/h|H/g, this.getHours());
     str = str.replace(/mm/, this.getMinutes() > 9 ? this.getMinutes().toString() : '0' + this.getMinutes());
     str = str.replace(/m/g, this.getMinutes());

     str = str.replace(/ss|SS/, this.getSeconds() > 9 ? this.getSeconds().toString() : '0' + this.getSeconds());
     str = str.replace(/s|S/g, this.getSeconds());
     return str;
}

function transfer01(value){
  let arr = ['', ]
  // 级联 nested嵌套  chain
  if(arr.indexOf(value) > -1){
    return '0'
  } else {
    return '1'
  }
}

function proxy_req(method, url, params, callback, modal, messageMap, showClose=true, showModal=false,){
  let loading, request;
  if(modal){
    loading = this.createLoading()
  }
  if(params){
    if(method == 'get'){
      // get(url, {params, config})
      request = this.$req[method](url, {params})
    } else {
      //  post(url, data, config)
      request = this.$req[method](url, params)
    }
  } else {
    if(method == 'get'){
      // get(url, {params, config})
      request = this.$req[method](url)
    } else {
      //  post(url, data, config)
      request = this.$req[method](url)
    }
  }
  request.then(res => {
    if(!showModal){
      this.$message({
        type: 'success',
        message: messageMap ? (messageMap["1"] ? messageMap["1"] : i18n.t("notification.operateSuccess")) : i18n.t("notification.operateSuccess"),
        showClose,
      })
    }
    if(loading){
      loading.close()
    }
    callback ? callback(res) : ''
  }).catch(err=> {
    // 重启 更新 复位 tokenExpired
    callback ? callback(err) : ''
    if(this.$store.state.info.showModal || err.code == "-1"){
      return
    }
    console.log("err")
    this.$message({
      type: 'warning',
      message: messageMap ? messageMap[err.code] : i18n.t("notification.operateFailed"),
      showClose,
    })
    //  兼容 全面 健壮性
    if(loading){
      loading.close()
    }
  }).finally(() => {
    console.log("ok")
    if(loading){
      loading.close()
    }
  })
}
// 获取元素坐标 rectangular 长方形
function getOffsetRect(elem) {
  var box = elem.getBoundingClientRect()
  var body = document.body
  var docElem = document.documentElement
  var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop
  var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft
  var clientTop = docElem.clientTop || body.clientTop || 0
  var clientLeft = docElem.clientLeft || body.clientLeft || 0
  var top  = box.top +  scrollTop - clientTop
  var left = box.left + scrollLeft - clientLeft
  return { top: Math.round(top), left: Math.round(left) }
}

function getOffsetSum(elem){
  let x=0, y=0;
  while(elem){
    x += parseInt(elem.offsetLeft)
    y += parseInt(elem.offsetTop)
    elem = elem.offsetParent
  }
  return { top: y, left: x, }
}
// 字符串格式化为获取到数据时显示正常
function formatValue(v, suffix){
  if(v){
    return v + (suffix ? suffix : '')
  } else {
    return "--"
  }
}
// setTimeout + 递归实现setInterval 定时器
function setTimer(fn, duration){
  let ref = {};
  ref.next = true
  let resource = ()=> {
    if(ref.next){
      ref.timeout = setTimeout(()=> {
        fn()
        resource()
      }, duration)
    }
  }
  resource()
  // 返回异步任务队列的引用指针
  return ref
}
// 销毁定时器 释放 清除队列
function clearTimer(ref) {
  ref.next = false
  clearTimeout(ref.timeout)
}

// 正则校验ip字符串的合法性
function isValidIP(...ip) {
  const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
  let flag = true
  try {
    ip.forEach(entry=> {
      if(!reg.test(entry)){
        flag = false
        Message({
          type: "warning",
          message: i18n.t("notification.typeValidIP"),
          showClose: true,
        })
        throw new Error()
      }
    })
  } catch(e){

  }
  return flag;
} 

// 校验主机地址的合法性
function isLegalHost(...host) {
  const ip = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
  const domain = /^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/
  let flag = true
  try {
    host.forEach(entry=> {
      if(ip.test(entry) || domain.test(entry)){
        return
      } else {
        flag = false
        Message({
          type: "warning",
          message: i18n.t("notification.typeValidIP"),
          showClose: true,
        })
        throw new Error()
      }
    })
  } catch(e){

  }
  return flag;
}

// 过滤有输入值的
function filterValue(...args){
  // filter不会改变原数组 会生成新数组
  args = args.filter(entry=> entry!=="" && entry!=="undefined")
  return args
}
// 多长时间内只执行一次
export function mydebounce(fn, wait = 3000){
  // 定时器timer在外层函数 内层事件处理函数 closure访问的都是同一个timer
  let timer = null
  return function() {
    // 此处能访问this vue实例对象
    // 不使用闭包  将timer计时器绑定给fn
    if(timer){
      return
    }
    fn.apply(this, arguments)
    timer = setTimeout(()=> {
      clearTimeout(timer)
      console.log(timer)
      timer = null
    }, wait)
  }
}

function mythrottle(){

}
// 字符串转大小写
function upperStr(s){
  s = s ? s.toUpperCase() : ""
  return s
}
function lowerStr(s){
  s = s ? s.toLowerCase() : ""
  return s
}

function goLogin(redirect="/home"){
  this.$router.push({
    path: "/login",
    query: {
      redirect,
    }
  })
}

function longLoading(method, url, params, callback, showModal, notiVar, notification,
  success, duration, loadingBefore=false, messageMap){
  // loadingBefore 之前的elementUI的loading遮罩
  // proxy_req(method, url, params, callback, modal, messageMap, showClose=true, showModal)
  // 函数内参数和this是动态的
  console.log(this, this[showModal], this[notification])
  // 最外层函数拿到上下文this得往内层函数传递  内层函数需要使用上下文执行环境
  if(loadingBefore){
    loadingBefore.close()
  }
  console.log(duration)
  this[showModal] = true
  this[notiVar] = notification
  this.$store.commit("info/set_modal", true)
  this.$store.commit("info/set_successMsg", success) // 集中存储提示信息
  this.proxy_req(method, url, params, err=> {
    if(err.code != "1"){
      console.log("err")
      this[showModal] = false
      this.$store.commit("info/set_modal", false)
    }
    this.$store.commit("info/set_successMsg", success) // 集中存储提示信息
    console.log("延时啦", this.$store.state.info.showModal)
    // this.goLogin()
    // this.$message({
    //   type: "success",
    //   message: success,
    //   showClose: true,
    // })
    // callback()
    // =========================================
    // new Promise((resolve, reject)=> {
    //   setTimeout(()=> {
    //     console.log("到点了")
    //     alert("到点了")
    //     callback()
    //     this[showModal] = false
    //     // this.goLogin()
    //     this.$message({
    //       type: "success",
    //       message: success,
    //       showClose: true,
    //     })
    //     this.$store.dispatch("user/resetState")
    //     // this 指向当前调用函数vue实例  路由走了实例就销毁了 
    //     router.push({
    //       path: "/login",
    //       query: {
    //         redirect: "/home"
    //       }
    //     })
    //     resolve()
    //   }, duration)
    // })
  }, false, messageMap, true, true )
}

function transferSignal(origin){
  let sign = parseInt(origin)
  sign < 0 ? sign = -sign : ""
  if(sign >= 0 && sign <= 25) {
    return 1
  } else if( sign <= 50 ) {
    return 2
  } else if( sign <= 75 ) {
    return 3
  } else {
    return 4
  }
}


export default { deepClone, buildTree,
formatDuration, transfer_total_traffic, formatByte,
value_to_label, arr_to_obj, obj_to_arr,
dateFormat, transfer01, proxy_req,
formatValue, setTimer, clearTimer, isValidIP, isLegalHost, filterValue,
mydebounce, mythrottle, upperStr, lowerStr, goLogin, longLoading,
transferSignal, 
}

